package com.ihome.framework.core.nos;

import java.net.URL;
import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ihome.framework.core.commons.BaseConst;
import com.ihome.framework.core.log.Log;

public class NosService {
	private static final Logger LOG = LoggerFactory.getLogger(NosService.class);

	@Resource
	IHomeNosClient nosClient;

	@Resource
	IHomeNosOldClient iHomeNosOldClient;

	@Resource
	NosConfig nosConfig;

	private static final String INSIDE = "inside";

	// 分配到上传token的默认有效时间,单位:秒
	private static final int DEFAULT_EXPIRE = 300;

	/**
	 * 获取公有桶上传文件的token
	 * 
	 * @param returnUrl
	 * @return
	 */
	public String getPubUploadToken(String returnUrl) {
		String bucketName = nosConfig.getPublicBucket();
		return getUploadToken(null, bucketName, returnUrl);
	}

	/**
	 * 获取公有桶上传文件的token
	 * 
	 * @param returnUrl
	 * @param key
	 *            指定文件上传后的key
	 * @return
	 */
	public String getPubUploadToken(String returnUrl, String key) {
		String bucketName = nosConfig.getPublicBucket();
		return getUploadToken(key, bucketName, returnUrl);
	}

	/**
	 * 获取私有桶上传文件的token
	 * 
	 * @param returnUrl
	 * @return
	 */
	public String getPriUploadToken(String returnUrl) {
		String bucketName = nosConfig.getPrivateBucket();
		return getUploadToken(null, bucketName, returnUrl);
	}

	/**
	 * 获取私有桶上传文件的token
	 * 
	 * @param returnUrl
	 * @param key
	 *            指定文件上传后的key
	 * @return
	 */
	public String getPriUploadToken(String returnUrl, String key) {
		String bucketName = nosConfig.getPrivateBucket();
		return getUploadToken(key, bucketName, returnUrl);
	}

	/**
	 * 获取公有桶文件的访问url
	 * 
	 * @param key
	 * @return
	 */
	public String getPubFileUrl(String key) {
		boolean flag = Boolean.parseBoolean(nosConfig.getIsOpen());
		LOG.info(Log.op("getPubFileUrl").msg("getPubFileUrl with new sdk start").kv("isOpen", nosConfig.getIsOpen())
				.toString());
		if (flag) {
			boolean isExist = nosClient.hasObject(nosConfig.getPublicBucket(), key);
			if (isExist) {
				LOG.info(
						Log.op("getPubFileUrl").msg("getPubFileUrl with compatible").kv("isExist", isExist).toString());
				return getNewPubFileUrl(key);
			} else {
				LOG.info(
						Log.op("getPubFileUrl").msg("getPubFileUrl with compatible").kv("isExist", isExist).toString());
				return getOldPubFileUrl(key);
			}
		} else {
			LOG.info(Log.op("getPubFileUrl").msg("getPubFileUrl without compatible").toString());
			return getNewPubFileUrl(key);
		}
	}

	/**
	 * 获取新公有桶链接
	 * 
	 * @param key
	 * @return
	 */
	private String getNewPubFileUrl(String key) {
		String url = "http://" + nosConfig.getPublicBucket() + "." + nosConfig.getHostName() + "/" + key;
		return url;
	}

	/**
	 * 获取旧公有桶链接
	 * 
	 * @param key
	 * @return
	 */
	private String getOldPubFileUrl(String key) {
		String url = "http://" + nosConfig.getOldHostName() + "/" + nosConfig.getPublicBucket() + "/" + key;
		return url;
	}

	/**
	 * 获取私有桶文件的访问url，默认5分钟过期
	 * 
	 * @param key
	 *            文件的key
	 * @return
	 */
	public String getPriFileUrl(String key) {
		return getPriFileUrl(key, DEFAULT_EXPIRE);
	}

	/**
	 * 获取私有桶文件的访问url，指定过期时间
	 * 
	 * @param key
	 *            文件的key
	 * @param expire
	 *            过期时间，单位：秒
	 * @return
	 */
	public String getPriFileUrl(String key, int expire) {
		boolean flag = Boolean.parseBoolean(nosConfig.getIsOpen());
		LOG.info(Log.op("getPriFileUrl").msg("getPriFileUrl with new sdk start").kv("isOpen", nosConfig.getIsOpen())
				.toString());
		if (flag) {
			boolean isExist = nosClient.hasObject(nosConfig.getPrivateBucket(), key);
			if (isExist) {
				LOG.info(
						Log.op("getPriFileUrl").msg("getPriFileUrl with compatible").kv("isExist", isExist).toString());
				return getNewPriFileUrl(key, expire);
			} else {
				LOG.info(
						Log.op("getPriFileUrl").msg("getPriFileUrl with compatible").kv("isExist", isExist).toString());
				return getOldPriFileUrl(key, expire);
			}
		} else {
			LOG.info(Log.op("getPriFileUrl").msg("getPriFileUrl without compatible").toString());
			return getNewPriFileUrl(key, expire);
		}

	}

	/**
	 * 获取新私有桶文件的访问url，指定过期时间
	 * 
	 * @param key
	 *            文件的key
	 * @param expire
	 *            过期时间，单位：秒
	 * @return
	 */
	private String getNewPriFileUrl(String key, int expire) {
		Date outdate = new Date(System.currentTimeMillis() + expire * BaseConst.SECOND);
		URL url = nosClient.generatePresignedUrl(nosConfig.getPrivateBucket(), key, outdate);
		String baseUrl = "http://" + nosConfig.getPrivateBucket() + "." + nosConfig.getHostName() + "/" + key;
		String reqUrl = url.getQuery();
		reqUrl = baseUrl + "?" + reqUrl;
		return reqUrl;
	}

	/**
	 * 获取旧私有桶文件的访问url，指定过期时间
	 * 
	 * @param key
	 *            文件的key
	 * @param expire
	 *            过期时间，单位：秒
	 * @return
	 */
	private String getOldPriFileUrl(String key, int expire) {
		Date outdate = new Date(System.currentTimeMillis() + expire * BaseConst.SECOND);
		URL url = iHomeNosOldClient.generatePresignedUrl(nosConfig.getPrivateBucket(), key, outdate);
		String baseUrl = "http://" + nosConfig.getOldHostName() + "/" + nosConfig.getPrivateBucket() + "/" + key;
		String reqUrl = url.getQuery();
		reqUrl = baseUrl + "?" + reqUrl;
		return reqUrl;
	}

	/**
	 * 生成上传文件的token
	 * 
	 * @param key
	 *            上传文件的key,若为null则内部自动生成
	 * @param bucketName
	 * @param returnUrl
	 * @return
	 */
	private String getUploadToken(String key, String bucketName, String returnUrl) {
		if (StringUtils.isBlank(key)) {
			key = new NosKey().withNamespace(nosConfig.getNamespace()).withSource(INSIDE)
					.withTimestamp(System.currentTimeMillis()).toKey();
		}
		int expires = NosAuthTool.currentTimeSeconds() + DEFAULT_EXPIRE;
		NosUpdatePolicy policy = new NosUpdatePolicy(bucketName, key, expires);
		String returnBody = new NosMagicVar().withBucket().withContentType().withObject().toJson();
		policy = policy.withReturnBody(returnBody);
		// 非空才加上,客户端直传可能不需要returnUrl
		if (StringUtils.isNotBlank(returnUrl)) {
			policy = policy.withReturnUrl(returnUrl);
		}
		String policyJson = policy.toJson();
		String token = NosAuthTool.getUploadToken(nosClient, policyJson, nosConfig.getAccessKey());
		return token;
	}

	public void setNosClient(IHomeNosClient nosClient) {
		this.nosClient = nosClient;
	}

	public void setNosConfig(NosConfig nosConfig) {
		this.nosConfig = nosConfig;
	}

	public void setiHomeNosOldClient(IHomeNosOldClient iHomeNosOldClient) {
		this.iHomeNosOldClient = iHomeNosOldClient;
	}

}
